package com.example.daxiguaforharmony.utils;

import ohos.app.Context;
import ohos.data.distributed.common.*;
import ohos.data.distributed.device.DeviceFilterStrategy;
import ohos.data.distributed.device.DeviceInfo;
import ohos.data.distributed.device.DeviceKvStore;
import ohos.data.distributed.user.SingleKvStore;
import ohos.hiviewdfx.HiLog;

import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;

/**
 * 分布式数据库管理类
 */
public class DbKvManager {
    //private static DbKvManager instance;
    private volatile static DbKvManager singleton;

//    public static synchronized DbKvManager getInstance(Context context) {
//        if (instance == null) {
//            instance = new DbKvManager(context);
//        }
//        return instance;
//    }

    public static DbKvManager getDbKvManager(Context context) {
        if (singleton == null) {
            synchronized (DbKvManager.class) {
                if (singleton == null) {
                    singleton = new DbKvManager( context);
                }
            }
        }
        return singleton;
    }

    SingleKvStore singleKvStore;
    KvManager kvManager;
    String DeviceId;

    /**
     * 配置构造分布式存储管理类
     */
    public DbKvManager(Context context) {
        try{
            System.out.println("创建db开始======");
            //Context context = this.Context();
            KvManagerConfig config = new KvManagerConfig(context);
            kvManager = KvManagerFactory.getInstance().createKvManager(config);
            DeviceId = kvManager.getLocalDeviceInfo().getId();
            System.out.println("DbKvManager DeviceId="+DeviceId);
            Options CREATE = new Options();
            //CREATE.setCreateIfMissing(true).setEncrypt(false).setKvStoreType(KvStoreType.SINGLE_VERSION).setAutoSync(true);//设置数据库不存在时创建
            CREATE.setCreateIfMissing(true).setEncrypt(false).setKvStoreType(KvStoreType.SINGLE_VERSION).setAutoSync(false);//设置数据库不存在时创建
            String storeID = "daxiguaforharmony";
            if (singleKvStore == null) {
                singleKvStore = kvManager.getKvStore(CREATE, storeID);
            }
            subscribe(singleKvStore);
            System.out.println("创建db end========");
        }
        catch (KvStoreException err)
        {
            System.out.println("创建db 失败=====err="+err.getMessage());
        }
    }

    public void init(Context context) {
        try{
            System.out.println("创建db开始======");
            //Context context = this.Context();
            KvManagerConfig config = new KvManagerConfig(context);
            kvManager = KvManagerFactory.getInstance().createKvManager(config);
            Options CREATE = new Options();
            CREATE.setCreateIfMissing(true).setEncrypt(false).setKvStoreType(KvStoreType.SINGLE_VERSION);//设置数据库不存在时创建
            String storeID = "daxiguaforharmony";
            singleKvStore = kvManager.getKvStore(CREATE, storeID);
            DeviceId = kvManager.getLocalDeviceInfo().getId();
            System.out.println("创建db end======");
        }
        catch (Exception err)
        {
            System.out.println("创建db 失败=====err="+err.getMessage());
        }
    }

    /**
     * 获取当前设备id
     * @return
     */
    public String getDeviceId()
    {
        //String deviceId = KvManagerFactory.getInstance().createKvManager(new KvManagerConfig(this)).getLocalDeviceInfo().getId();//获取当前设备id
        String deviceId = DeviceId;//获取当前设备id
        return deviceId;
    }

    /**
     * 写入数据
     *
     * @param key
     * @param value
     * @return
     */
    public void write(String key, String value) {
        try{
            if(key.isEmpty())
            {
                throw new Exception("key 不能为空===");
            }
            System.out.println("开始写入数据====" + key + "===" + value);
            singleKvStore.putString(key, value);
            System.out.println("结束写入数据====" + key);
        }
        catch (Exception err)
        {
            System.out.println("写入失败了!!! err==="+err.getMessage());
        }



    }

    public void writeAll(List<Entry> entryList) {
        try{
            if(entryList.isEmpty())
            {
                throw new Exception("key 不能为空===");
            }
            System.out.println("开始写入数据====" + entryList+ "===" );

            singleKvStore.putBatch(entryList);
            System.out.println("结束写入数据====" );
        }
        catch (Exception err)
        {
            System.out.println("写入失败了!!! err==="+err.getMessage());
        }



    }

    /**
     * 读取数据
     *
     * @param key
     * @return
     */
    public String read(String key) {
        try {
            System.out.println("开始读取数据====" + key);
            String value = singleKvStore.getString(key);
            System.out.println("结束读取数据====" + key+" value="+value);
            return value;
        }
        catch (Exception err)
        {
            try {
                singleKvStore.putString(key, "0");
                System.out.println("db读取err===="+err.getMessage());
                return "";
            }
            catch (Exception err2)
            {
                //singleKvStore.putString(key, "0");
                System.out.println("db2读取err===="+err2.getMessage());
                return "";
            }
        }

    }

//    public String readAll(String key) {
//        try {
//            System.out.println("开始读取数据====" + key);
//            String value = singleKvStore.getEntries(key);
//            System.out.println("结束读取数据====" + key+" value="+value);
//            return value;
//        }
//        catch (Exception err)
//        {
//            try {
//                singleKvStore.putString(key, "0");
//                System.out.println("db读取err===="+err.getMessage());
//                return "";
//            }
//            catch (Exception err2)
//            {
//                //singleKvStore.putString(key, "0");
//                System.out.println("db2读取err===="+err2.getMessage());
//                return "";
//            }
//        }
//
//    }

    public List<String> getDeviceList()
    {
        List<String> deviceIdList = new ArrayList<>();
        try {
            System.out.println("获取已连接的设备列表 getDeviceList ====");
            List<DeviceInfo> deviceInfoList = kvManager.getConnectedDevicesInfo(DeviceFilterStrategy.NO_FILTER);
            System.out.println("device size=== " + deviceInfoList.size());
            if(deviceInfoList.size()>0)
            {
                for (DeviceInfo deviceInfo : deviceInfoList) {
                    deviceIdList.add(deviceInfo.getId());
                }
                singleKvStore.sync(deviceIdList, SyncMode.PUSH_PULL);//PUSH_ONLY
            }
            return deviceIdList;

        }
        catch (Exception err)
        {
            err.printStackTrace();
            System.out.println("getDeviceList err===="+err.getClass()+"=="+err.getMessage());
            return deviceIdList;
        }
    }



    /**
     * 同步数据到其他设备。
     * 1. 获取已连接的设备列表。
     * 2. 选择同步方式进行数据同步。
     * 以下为单版本分布式数据库进行数据同步的代码示例，其中同步方式为PUSH_ONLY：
     */
    public void syncDeviceData(List<String> deviceIdList) {
        //System.out.println("获取已连接的设备列表 syncDeviceData ====");
        //List<DeviceInfo> deviceInfoList = kvManager.getConnectedDevicesInfo(DeviceFilterStrategy.NO_FILTER);
        System.out.println("device size=== " + deviceIdList.size());
        //List<String> deviceIdList = new ArrayList<>();

        if(deviceIdList.size()>0)
        {
            singleKvStore.sync(deviceIdList, SyncMode.PULL_ONLY);//PUSH_ONLY
        }

    }

    private void syncContact() {
        List<DeviceInfo> deviceInfoList = kvManager.getConnectedDevicesInfo(DeviceFilterStrategy.NO_FILTER);
        List<String> deviceIdList = new ArrayList<>();
        for (DeviceInfo deviceInfo : deviceInfoList) {
            deviceIdList.add(deviceInfo.getId());
        }
        //HiLog.info( "device size= " + deviceIdList.size());
        System.out.println("device size=== " + deviceIdList.size());
        if (deviceIdList.size() == 0) {
            //showTip("组网失败");
            System.out.println("组网失败0");
            return;
        }
//        singleKvStore.registerSyncCallback(new SyncCallback() {
//            @Override
//            public void syncCompleted(Map<String, Integer> map) {
//                getUITaskDispatcher().asyncDispatch(new Runnable() {
//                    @Override
//                    public void run() {
//                        queryContact();
//                        showTip("同步成功");
//                    }
//                });
//                singleKvStore.unRegisterSyncCallback();
//            }
//        });
        singleKvStore.sync(deviceIdList, SyncMode.PUSH_PULL);
    }

    /**
     * 订阅单版本分布式数据库所有（本地及远端）数据变化通知
     */
    public void subscribe(SingleKvStore singleKvStore)
    {
        KvStoreObserver kvStoreObserverClient = new KvStoreObserverClient();
        singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, kvStoreObserverClient);
    }


    /**
     * 关闭数据库
     */
    public void close()
    {
        //kvManager.closeKvStore(singleKvStore);
    }

    /**
     * 删除Db
     * @param storeID
     */
    public void deleteDb(String storeID)
    {
        //kvManager.deleteKvStore(storeID);
    }
}

/**
 * Receive database messages
 */
//private class KvStoreObserverClient implements KvStoreObserver {
//    @Override
//    public void onChange(ChangeNotification notification) {
//        getUITaskDispatcher().asyncDispatch(new Runnable() {
//            @Override
//            public void run() {
//                HiLog.info(LABEL_LOG, LOG_FORMAT,TAG, "come to auto sync");
//                queryContact();
//                showTip("同步成功");
//            }
//        });
//    }
//}

class KvStoreObserverClient implements KvStoreObserver {
    @Override
    public void onChange(ChangeNotification notification) {
        List<Entry> insertEntries = notification.getInsertEntries();
        List<Entry> updateEntries = notification.getUpdateEntries();
//        Entry entry = new Entry();
//        entry.setKey("score_friend");
//        updateEntries.set(0,entry);
        List<Entry> deleteEntries = notification.getDeleteEntries();

    }
}